<?php

namespace SunAdmin\Service;

use SunAdmin\Common\Utils;
use SunAdmin\Model\TimerTaskLogModel;
use SunAdmin\Model\TimerTaskModel;
use think\facade\Log;
use Monolog\Handler\Curl\Util;

class TimerTaskService
{
    public static function getTaskList($page = 0,$limit = 0){
        $query = TimerTaskModel::when($page > 0, function ($query) use ($page, $limit) {
            $query->page($page, $limit);
        });
        $count = $query->count();
        $list = $query->order('id desc')->select();
        return compact('count','list');
    }

    public static function save($params){
        validate([
            'name' => 'require|alphaNum|max:50',
            'type' => 'require|in:interval,daily,weekly,monthly,cron',
            'schedule_config' => 'require|array',
            'class_name' => 'require|max:100',
            'method_name' => 'require|alpha|max:50'
        ])->check([
            'name' => $params['name'],
            'type' => $params['type'],
            'schedule_config' => $params['schedule_config'],
            'class_name' => $params['class_name'],
            'method_name' => $params['method_name']
        ]);
        //进一步校验schedule_config,如果type是interval,那么schedule_config必须包含interval大于零的整数或小数),如果type是daily,那么schedule_config必须包含time(格式示例11:10或者23:59)
        switch ($params['type']) {
            case 'interval':
                if (!isset($params['schedule_config']['interval']) || !is_numeric($params['schedule_config']['interval']) || $params['schedule_config']['interval'] <= 0) {
                    throw new \Exception('间隔执行任务的间隔时间必须是大于0的数字（毫秒）');
                }
                break;
                
            case 'daily':
                if (!isset($params['schedule_config']['time']) || !preg_match('/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/', $params['schedule_config']['time'])) {
                    throw new \Exception('每日执行任务的时间格式必须是 HH:MM（如：09:30）');
                }
                break;
                
            case 'weekly':
                if (!isset($params['schedule_config']['day_of_week']) || !in_array($params['schedule_config']['day_of_week'], [0,1,2,3,4,5,6])) {
                    throw new \Exception('每周执行任务的星期必须是0-6的数字（0为周日）');
                }
                if (!isset($params['schedule_config']['time']) || !preg_match('/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/', $params['schedule_config']['time'])) {
                    throw new \Exception('每周执行任务的时间格式必须是 HH:MM');
                }
                break;
                
            case 'monthly':
                if (!isset($params['schedule_config']['day_of_month']) || !is_numeric($params['schedule_config']['day_of_month']) || 
                    $params['schedule_config']['day_of_month'] < 1 || $params['schedule_config']['day_of_month'] > 31) {
                    throw new \Exception('每月执行任务的日期必须是1-31的数字');
                }
                if (!isset($params['schedule_config']['time']) || !preg_match('/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/', $params['schedule_config']['time'])) {
                    throw new \Exception('每月执行任务的时间格式必须是 HH:MM');
                }
                break;
                
            case 'cron':
                if (!isset($params['schedule_config']['cron']) || !self::isValidCronExpression($params['schedule_config']['cron'])) {
                    throw new \Exception('Cron表达式格式无效');
                }
                break;
        }
        //根据$params中的id是否大于零来判断是新增还是编辑修改.
        if($params['id']){
            $task = TimerTaskModel::find($params['id']);
            if (!$task) {
                throw new \Exception("任务id不存在");
            }
            if(TimerTaskModel::where([
                ['id', '<>', $task->id],
                ['name', '=', $params['name']],
            ])->count()){
                throw new \Exception("任务名称已经存在");
            }
        }else{
            if(TimerTaskModel::where([
                ['name', '=', $params['name']],
            ])->count()){
                throw new \Exception("任务名称已经存在");
            }
        }
        $params['add_time'] = Utils::timeToStr();
        TimerTaskModel::update($params);
        return true;
    }
    /**
     * 验证Cron表达式
     * @param string $expression
     * @return bool
     */
    private static function isValidCronExpression($expression)
    {
        $parts = explode(' ', trim($expression));
        if (count($parts) !== 5) {
            return false;
        }
        // 简单的Cron表达式验证（实际项目中建议使用专业的Cron解析库）
        $patterns = [
            '/^(\*|[0-5]?\d)$/',           // 分钟 (0-59)
            '/^(\*|1?\d|2[0-3])$/',        // 小时 (0-23)
            '/^(\*|[12]?\d|3[01])$/',      // 日 (1-31)
            '/^(\*|[1-9]|1[0-2])$/',       // 月 (1-12)
            '/^(\*|[0-6])$/'               // 星期 (0-6)
        ];
        foreach ($parts as $index => $part) {
            if (!preg_match($patterns[$index], $part)) {
                return false;
            }
        }
        return true;
    }
    public static function getTaskLogs($where = [],$page = 0,$limit = 0){
        $query = TimerTaskLogModel::when(!empty($where['task_id']), function ($query) use ($where) {
            $query->where('task_id', $where['task_id']);
        })->when(isset($where['status']), function ($query) use ($where) {
            $query->where('status', $where['status']);
        });
        $count = $query->count();
        $list = $query->with(['timerTask'])->order('id desc')->when($page > 0,function($q)use($page,$limit){
            $q->page($page, $limit);
        })->select();
        return compact('count','list');
    }

    /**
     * 手动执行任务
     * @param int $taskId 任务ID
     * @throws \Exception
     */
    public static function manualExecute($taskId)
    {
        // 获取任务信息
        $task = TimerTaskModel::find($taskId);
        if (!$task) {
            throw new \Exception('任务不存在');
        }

        if (!$task->enabled) {
            throw new \Exception('任务已禁用，无法执行');
        }
        $className = $task->class_name;
        $methodName = $task->method_name;

        // 检查类和方法是否存在
        if (!class_exists($className)) {
            throw new \Exception("任务类不存在: " . $className);
        }

        $taskInstance = new $className();
        if (!method_exists($taskInstance, $methodName)) {
            throw new \Exception("任务方法不存在: " . $className . "::" . $methodName);
        }
        // 执行任务
        $taskInstance->$methodName($taskId);
    }
}